package com.AndEngine.game;

import java.util.HashMap;

import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.entity.text.TextOptions;
import org.andengine.entity.util.FPSLogger;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.font.FontFactory;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.atlas.bitmap.BuildableBitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.source.IBitmapTextureAtlasSource;
import org.andengine.opengl.texture.atlas.buildable.builder.BlackPawnTextureAtlasBuilder;
import org.andengine.opengl.texture.atlas.buildable.builder.ITextureAtlasBuilder.TextureAtlasBuilderException;
//import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.ui.activity.BaseGameActivity;
import org.andengine.util.HorizontalAlign;
import org.andengine.util.debug.Debug;
//import org.andengine.engine.camera.Camera;
import org.andengine.engine.camera.BoundCamera;
import org.andengine.engine.camera.SmoothCamera;
import org.andengine.engine.camera.ZoomCamera;
import org.andengine.engine.camera.hud.HUD;
import org.andengine.extension.tmx.TMXLayer;
import org.andengine.extension.tmx.TMXLoader;
import org.andengine.extension.tmx.TMXProperties;
import org.andengine.extension.tmx.TMXTile;
import org.andengine.extension.tmx.TMXTileProperty;
import org.andengine.extension.tmx.TMXTiledMap;
import org.andengine.extension.tmx.TMXLoader.ITMXTilePropertiesListener;
import org.andengine.extension.tmx.util.exception.TMXLoadException;
import org.andengine.input.touch.TouchEvent;
import org.andengine.input.touch.controller.MultiTouch;
import org.andengine.input.touch.detector.ClickDetector;
import org.andengine.input.touch.detector.ClickDetector.IClickDetectorListener;
import org.andengine.input.touch.detector.PinchZoomDetector;
import org.andengine.input.touch.detector.ScrollDetector;
import org.andengine.input.touch.detector.SurfaceScrollDetector;
import org.andengine.input.touch.detector.PinchZoomDetector.IPinchZoomDetectorListener;
import org.andengine.input.touch.detector.ScrollDetector.IScrollDetectorListener;

//import android.os.Bundle;
//import android.app.Activity;
import android.graphics.Color;
import android.graphics.Typeface;
//import android.view.Menu;
import android.view.MotionEvent;
import android.widget.Toast;

public class GameActivity extends BaseGameActivity implements IOnSceneTouchListener, IScrollDetectorListener, IPinchZoomDetectorListener, IClickDetectorListener {


	//CONSTANTS
	private Scene mScene;
	protected static final int CAMERA_WIDTH = 480;
	protected static final int CAMERA_HEIGHT = 320;
    private static final int TILE_WIDTH = 16;
    private static final int TILE_HEIGHT = 16;
    private static final int DIALOG_ALLOWDIAGONAL_ID = 0;    
    //Controls the speed the sprite will move at. Lower is faster    
    private static final float mSpeed = (float) 0.3;
	
	//Textures
	private TiledTextureRegion mPlayerTextureRegion;
	private BuildableBitmapTextureAtlas mBitmapTextureAtlas;	
	
	//Camera
	private SmoothCamera mCamera;
	
	// Camera movement speeds
	final float maxVelocityX = 10;
	final float maxVelocityY = 5;
	// Camera zoom speed
	final float maxZoomFactorChange = 5;	
	
	//Pinch Zoom
	private SurfaceScrollDetector mScrollDetector;
	private PinchZoomDetector mPinchZoomDetector;
	private float mPinchZoomStartedCameraZoomFactor;
	boolean clicked = false;
	
	
	//touch Locations
	private float mTouchX = 0, mTouchY = 0, mTouchOffsetX = 0, mTouchOffsetY = 0;
	
	
	//map
	private TMXTiledMap mTMXTiledMap;
    private TMXLayer tmxLayer;
    private TMXTile tmxTile;
    private AnimatedSprite player;
   // private org.anddev.andengine.util.path.Path A_path;
   // private AStarPathFinder<TMXLayer> finder;
    private float[] playerFootCordinates;
   // private Path mCurrentPath;      
	private boolean isWalking;
	private int mWaypointIndex;
	//private PathModifier mMoveModifier;
	//private IEntityModifier mPathTemp;
	private String test;
	private int cCounter = 0;

	
	//Map generation
	dungeon generator;
	final static int TILE_SIZE = 8;
	int mapSizeX = 20;
	int mapSizeY = 20;
	int mapRoomObjects = 10;
	
	//CONSTRUCTORS
	
	// HUD Text and HUD
    private BitmapTextureAtlas mFontTexture;
    private Font mFont;
    HUD hud = new HUD();
    private float maxZoom;
	
	
	@Override
	public EngineOptions onCreateEngineOptions() {
		// TODO Auto-generated method stub
		//this.mCamera = new ZoomCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		this.mCamera = new SmoothCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT, maxVelocityX, maxVelocityY, maxZoomFactorChange);
		EngineOptions options = new EngineOptions(true,
				ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(
						CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera);
//        final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH , CAMERA_HEIGHT), this.mCamera);
    	//Sets the touch interactions to get processed during the update thread??
//   	engineOptions.getTouchOptions().setRunOnUpdateThread(true); 

    	//Attach HUD to the Camera
    	mCamera.setHUD(this.hud);
		
		if(MultiTouch.isSupported(this)) {
			if(MultiTouch.isSupportedDistinct(this)) {
				//Toast.makeText(this, "MultiTouch detected --> Both controls will work properly!", Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(this, "MultiTouch detected, but your device has problems distinguishing between fingers.\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
			}
		} else {
			Toast.makeText(this, "Sorry your device does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
		}		
		
		Toast.makeText(this, "Welcome!!", Toast.LENGTH_SHORT).show();
		
		return options;
	}

	@Override
	public void onCreateResources(
			OnCreateResourcesCallback pOnCreateResourcesCallback)
			throws Exception {

    	// HUD text
		this.mFont = FontFactory.create(this.getFontManager(), this.getTextureManager(), 256, 256, Typeface.create(Typeface.DEFAULT, Typeface.BOLD), 16);
		this.mFont.load();
		
		//Set graphics base path
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

		//Load texture atlas
		this.mBitmapTextureAtlas = new BuildableBitmapTextureAtlas(this.getTextureManager(), 512, 256, TextureOptions.NEAREST);
//		this.mBitmapTextureAtlas = new BuildableBitmapTextureAtlas(this.getTextureManager(), 512, 256, TextureOptions.BILINEAR);
		
		//set player texture
		this.mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "player_tiled.png", 2, 1);
				
		// Resources Loaded
		pOnCreateResourcesCallback.onCreateResourcesFinished();

	}

	@Override
	public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)
			throws Exception {

		this.mEngine.registerUpdateHandler(new FPSLogger());
		this.mScene = new Scene();
		
		
		try {
			final TMXLoader tmxLoader = new TMXLoader(this.getAssets(), this.mEngine.getTextureManager(), TextureOptions.BILINEAR_PREMULTIPLYALPHA, this.getVertexBufferObjectManager(), new ITMXTilePropertiesListener() {
				@Override
				public void onTMXTileWithPropertiesCreated(final TMXTiledMap pTMXTiledMap, final TMXLayer pTMXLayer, final TMXTile pTMXTile, final TMXProperties<TMXTileProperty> pTMXTileProperties) {

				}
			});
			this.mTMXTiledMap = tmxLoader.loadFromAsset("mymap.tmx");

		} catch (final TMXLoadException e) {
			Debug.e(e);
		}

		final TMXLayer tmxLayer = this.mTMXTiledMap.getTMXLayers().get(0);
		this.mScene.attachChild(tmxLayer);		
		
		/* Make the camera not exceed the bounds of the TMXEntity. */
//		this.mCamera.setBounds(0, 0, tmxLayer.getHeight(), tmxLayer.getWidth());
//		this.mCamera.setBoundsEnabled(true);

		this.mScene.setOnAreaTouchTraversalFrontToBack();
		
		//this.mScene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));

		this.mScrollDetector = new SurfaceScrollDetector(this);
		this.mPinchZoomDetector = new PinchZoomDetector(this);

		this.mScene.setOnSceneTouchListener(this);
		this.mScene.setTouchAreaBindingOnActionDownEnabled(true);		
		
		
		/* Position Player. */
		this.player = new AnimatedSprite(100, 100, this.mPlayerTextureRegion, this.getVertexBufferObjectManager());
		this.player.animate(100);
		this.mScene.attachChild(this.player);
		this.mCamera.setChaseEntity(player);

		//Create Dungeon
		generator = new dungeon();
		generator.createDungeon(mapSizeX, mapSizeY, mapRoomObjects);		
		
		//DEBUG DUNGEON
		final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();
		final Text leftText = new Text(10, 10, this.mFont, generator.showDungeon(), new TextOptions(HorizontalAlign.LEFT), vertexBufferObjectManager);
		this.mScene.attachChild(leftText);
		
		pOnCreateSceneCallback.onCreateSceneFinished(this.mScene);
	}

	@Override
	public void onPopulateScene(Scene pScene,
			OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {

		// Populate Scene
		//Sprite sPlayer = new Sprite(CAMERA_WIDTH/2, CAMERA_HEIGHT/2, playerTextureRegion, this.mEngine.getVertexBufferObjectManager());
		//sPlayer.setRotation(45.0f);
		//this.scene.attachChild(sPlayer);
		
		pOnPopulateSceneCallback.onPopulateSceneFinished();
	}

    


	@Override
	public void onScrollStarted(final ScrollDetector pScrollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY) {
		final float zoomFactor = this.mCamera.getZoomFactor();
		this.mCamera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY / zoomFactor);
	}

	@Override
	public void onScroll(final ScrollDetector pScrollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY) {
		final float zoomFactor = this.mCamera.getZoomFactor();
		this.mCamera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY / zoomFactor);
	}
	
	@Override
	public void onScrollFinished(final ScrollDetector pScrollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY) {
		final float zoomFactor = this.mCamera.getZoomFactor();
		this.mCamera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY / zoomFactor);
	}

	@Override
	public void onPinchZoomStarted(final PinchZoomDetector pPinchZoomDetector, final TouchEvent pTouchEvent) {
		this.mPinchZoomStartedCameraZoomFactor = this.mCamera.getZoomFactor();
	}

	@Override
	public void onPinchZoom(final PinchZoomDetector pPinchZoomDetector, final TouchEvent pTouchEvent, final float pZoomFactor) {
		this.mCamera.setZoomFactor(this.mPinchZoomStartedCameraZoomFactor * pZoomFactor);
	}

	@Override
	public void onPinchZoomFinished(final PinchZoomDetector pPinchZoomDetector, final TouchEvent pTouchEvent, final float pZoomFactor) {
		this.mCamera.setZoomFactor(this.mPinchZoomStartedCameraZoomFactor * pZoomFactor);
	}


	@Override
	public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
		this.mPinchZoomDetector.onTouchEvent(pSceneTouchEvent);

		if(this.mPinchZoomDetector.isZooming()) {
			this.mScrollDetector.setEnabled(false);
		} else {
			if(pSceneTouchEvent.isActionDown()) {
				this.mScrollDetector.setEnabled(true);
			}
			this.mScrollDetector.onTouchEvent(pSceneTouchEvent);
		}

		return true;
	}

	@Override
	public void onClick(ClickDetector pClickDetector, int pPointerID,
			float pSceneX, float pSceneY) {
		// TODO Auto-generated method stub
		
	}

	
	//onload example
	/*
	dungeon generator;
	PFont font;
	String mapDisplay;
	PImage dungeonMap;
	final static int TILE_SIZE = 8;
	int mapSizeX = 70;
	int mapSizeY = 70;
	int mapRoomObjects = 40;
	 
	void setup() {
	  size(mapSizeX * TILE_SIZE, mapSizeY * TILE_SIZE);
	  font = createFont("Courier New", 12);
	  textFont(font);
	  fill(255);
	  noSmooth();
	  generator = new dungeon();
	  getNewDungeonMap();
	}
	 
	void draw() {
	  background(0);
	  image(dungeonMap, 0, 0);
	  //text(generator.showDungeon(), 6, 36);
	}
	 
	void getNewDungeonMap() {
	  generator.createDungeon(mapSizeX, mapSizeY, mapRoomObjects);
	  dungeonMap = generator.generateDungeonImage();
	}
	 
	void keyReleased() {
	  if (key == ' ') getNewDungeonMap();
	}
	*/
	
	
	
	
}
